﻿//----------------------------------------------------------------
// Copyright (c) 2011-2013 
// All rights reserved.
// Author: Ben DaoWei 
// Contact: bendaowei@gmail.com
// Web Link: http://xnaeditor.codeplex.com
// ----------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MdxLib.Model;
using Microsoft.Xna.Framework;
using MdxLib.Animator;
using MdxLib.Primitives;

namespace UnityEngine.Graphics
{
    public class NodeRenderer
    {
        public INode Node { get; set; }

        public int NodeId
        {
            get
            {
                return this.Node.NodeId;
            }
        }

        public int ParentNodeId
        {
            get
            {
                return this.Node.Parent.NodeId;
            }
        }

        public Matrix World { get; set; }

        private Matrix translation;
        private Matrix rotation;
        private Matrix scaling;

        public NodeRenderer(INode node)
        {
            this.Node = node;
            this.Node.Translation.MakeAnimated();
            this.Node.Rotation.MakeAnimated();
            this.Node.Scaling.MakeAnimated();
        }

        public void Update(int CurrentKeyFrame)
        {
            this.translation = GetTranslationMatrix(CurrentKeyFrame);
            this.rotation = GetRotationMatrix(CurrentKeyFrame);
            this.scaling = GetScalingMatrix(CurrentKeyFrame);

            Vector3 point = new Vector3(this.Node.PivotPoint.X, this.Node.PivotPoint.Y, this.Node.PivotPoint.Z);
            Vector3 pivor = Vector3.Transform(point, this.translation);
            this.World = Matrix.CreateTranslation(-pivor) *
                          this.rotation * this.scaling *
                          Matrix.CreateTranslation(pivor);
        }

        private Matrix GetTranslationMatrix(int frame)
        {
            MdxLib.Animator.CAnimator<MdxLib.Primitives.CVector3> trans = this.Node.Translation;

            CVector3 vec = trans.GetValue(new CTime(frame));

            return Matrix.CreateTranslation(vec.X, vec.Y, vec.Z);
        }

        private Matrix GetRotationMatrix(int frame)
        {
            MdxLib.Animator.CAnimator<MdxLib.Primitives.CVector4> rotation = this.Node.Rotation;

            CVector4 vec = rotation.GetValue(new CTime(frame));

            return Matrix.CreateFromQuaternion(new Quaternion(vec.X, vec.Y, vec.Z, vec.W));
        }

        private Matrix GetScalingMatrix(int frame)
        {
            MdxLib.Animator.CAnimator<MdxLib.Primitives.CVector3> scale = this.Node.Scaling;

            CVector3 vec = scale.GetValue(new CTime(frame));

            return Matrix.CreateScale(vec.X, vec.Y, vec.Z);
        }
    }

    public class BoneRenderer : NodeRenderer
    {
        public BoneRenderer(CBone bone)
            : base(bone)
        {
        }
    }

    public class LightRenderer : NodeRenderer
    {
        public LightRenderer(CLight light)
            : base(light)
        {
        }
    }

    public class HelpersRenderer : NodeRenderer
    {
        public HelpersRenderer(CHelper helper)
            : base(helper)
        {
        }
    }

    public class AttachmentRenderer : NodeRenderer
    {
        public AttachmentRenderer(CAttachment attachement)
            : base(attachement)
        {
        }
    }

    public class ParticleEmitterRenderer : NodeRenderer
    {
        public ParticleEmitterRenderer(CParticleEmitter emitter)
            : base(emitter)
        {
        }
    }

    public class ParticleEmitter2sRenderer : NodeRenderer
    {
        public ParticleEmitter2sRenderer(CParticleEmitter2 emitter)
            : base(emitter)
        {
        }
    }

    public class RibbonEmitterRenderer : NodeRenderer
    {
        public RibbonEmitterRenderer(CRibbonEmitter emitter)
            : base(emitter)
        {
        }
    }

    public class EventObjectRenderer : NodeRenderer
    {
        public EventObjectRenderer(CEvent eventObj)
            : base(eventObj)
        {
        }
    }

    public class CollisionShapeRenderer : NodeRenderer
    {
        public CollisionShapeRenderer(CCollisionShape shape)
            : base(shape)
        {
        }
    }
}
